/*****************************************************************************
 *  This file is part of the OpenDomo project.
 *  Copyright(C) 2011 OpenDomo Services SL
 *  
 *  Daniel Lerch Hostalot <dlerch@opendomo.com>
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *****************************************************************************/

// ----------------------------------------------------------------------------
// author: Daniel Lerch <dlerch@gmail.com>, http://www.opendomo.com
// date: APRIL 2009
//
// CHANGES:
//
// ----------------------------------------------------------------------------


#include <stdio.h>
#include <conf.h>
#include <chain.h>
#include <time.h>
#include <ds/hashtable.h>
#include <ds/string.h>
#include <ds/queue.h>


void add_event_to_list(char *event)
{
   FILE *f = fopen(EVENTLIST_FILE, "a+");
   if(!f)
   {
      perror("fopen()");
      return;
   }

   fprintf(f, "%ld\t%s\n", time(NULL), event);
   fclose(f);
}




void load_and_predict(void *hashtable, size_t tablesize)
{
   long timestamp = 0;
   long last_timestamp = 0;
   char string[64];

   HASHTABLE_PTR(ht, tablesize, chain_t*);
   ht = hashtable;

   FILE *f = fopen(EVENTLIST_FILE, "r");
   if(!f)
   {
      perror("fopen()");
      return;
   }

   QUEUE_CREATE(event_chain_queue, char*);

   /* read events file */
   while(!feof(f))
   {
      char *event_str = NULL;
      chain_t *chain = NULL;

      last_timestamp = timestamp;
      fscanf(f, "%ld\t%64s\n", &timestamp, string);

      /* enqueue chained events */
      if(timestamp-last_timestamp < EVENT_CHAIN_INTERVAL)
      {  
         //printf("%s\n", string);
         STRING_ASSIGN_FROM_STR(event_str, string);
         QUEUE_ENQUEUE(event_chain_queue, event_str);
      }
      else
      {
         /* dequeues chained events and adds to hashtable */
         while(QUEUE_SIZE(event_chain_queue)>0)
         {
            /* first size-1 events are prefix */
            STRING_CREATE_FROM_STR(key, "");
            while(QUEUE_SIZE(event_chain_queue)>1)
            {
               event_str = QUEUE_GET_HEAD(event_chain_queue);
               if(event_str)
               {
                  STRING_APPEND_STR(key, event_str);
                  STRING_APPEND_STR(key, "-");
                  STRING_DESTROY(event_str);
                  QUEUE_DEQUEUE(event_chain_queue);
               }
            }
         
            if(strlen(key)==0)
            {
               QUEUE_DEQUEUE(event_chain_queue);
               continue;
            }
   

            event_str = QUEUE_GET_HEAD(event_chain_queue);


            HASHTABLE_GET(ht, key, chain);
            if(!chain)
            {
               /* adds new element to hashtable */
               MALLOC_CHAIN(chain);
               STRING_ASSIGN_FROM_STR(chain->str, event_str);
               chain->count++;
               HASHTABLE_SET(ht, key, chain);  
            }
            else
            {
               /* increment counter in a repeated value */
               if(strcmp(chain->str, event_str)==0)
               {
                  chain->count++;
               }
               else
               {
                  /* decrement counter in a new value or replace it */
                  if(chain->count > 0)
                     chain->count = chain->count - chain->count/4 - 1;
                  else
                     STRING_ASSIGN_FROM_STR(chain->str, event_str);
               }
            }
            //printf("[%s] => [%s (%d)]\n", key, chain->str, chain->count);

            STRING_DESTROY(key);
            STRING_DESTROY(event_str);
            QUEUE_DEQUEUE(event_chain_queue);
         }

         //puts("BLOQUE: ");
         //printf("%s\n", string);
         STRING_CREATE_FROM_STR(event_str, string);
         QUEUE_ENQUEUE(event_chain_queue, event_str);
      }
   
   }


   STRING_CREATE_FROM_STR(key, "");
   while(QUEUE_SIZE(event_chain_queue)>0)
   {
      char *event_str = QUEUE_GET_HEAD(event_chain_queue);
      if(event_str)
      {
         STRING_APPEND_STR(key, event_str);
         STRING_APPEND_STR(key, "-");
         STRING_DESTROY(event_str);
         QUEUE_DEQUEUE(event_chain_queue);
      }
   }

   if(strlen(key)!=0)
   {
      chain_t *chain = NULL;
      HASHTABLE_GET(ht, key, chain);

      if(chain)
      {
         if(chain->count >= MIN_EVENT_PREDICTION )
         {
            printf("AUTO EVENT: %s\n", chain->str);
            //add_event_to_list(chain->str);
         }
      }
   }




   QUEUE_DESTROY(event_chain_queue); 

   fclose(f);
}


int main(int argc, char *argv[])
{
   if(argc!=2)
   {
      printf("Usage: %s [event]\n\n", argv[0]);
      return 0;
   }
 
   HASHTABLE_CREATE(ht, EVENTS_HT_SIZE, chain_t*);
   
   add_event_to_list(argv[1]);
   load_and_predict(ht, EVENTS_HT_SIZE);  

   HASHTABLE_DESTROY(ht);

   return 0;
}


